`timescale 1 ns /  100 ps
module spi_interface_test_bench();

reg clock, resetn, fifo_tx_empty, fifo_rx_full, spi_miso, start;
reg [7:0] fifo_tx_readdata, read_count;

wire fifo_tx_re, fifo_rx_we, spi_cs, spi_clk, spi_mosi, done;
wire [7:0] fifo_rx_writedata;

spi_interface DUT
(
	.clock(clock),
	.resetn(resetn),
	
	.fifo_tx_re(fifo_tx_re),
	.fifo_tx_empty(fifo_tx_empty),
	.fifo_tx_readdata(fifo_tx_readdata),

	.fifo_rx_we(fifo_rx_we),
	.fifo_rx_full(fifo_rx_full),
	.fifo_rx_writedata(fifo_rx_writedata),
	
	.spi_cs(spi_cs),
	.spi_clk(spi_clk),
	.spi_mosi(spi_mosi),
	.spi_miso(spi_miso),
	
	.start(start),
	.read_count(read_count),
	.done(done)
);

initial
begin
	// initialize
	clock = 1'b1;
	resetn = 1'b1;
	fifo_tx_empty = 1'b0;
	fifo_rx_full = 1'b0;
	spi_miso = 1'b0;
	start = 1'b0;
	fifo_tx_readdata=8'h00;
	read_count=1;

	@(posedge clock)
	resetn = 1'b0;
	@(posedge clock)
	@(posedge clock)
	resetn = 1'b1;

	// master transfer 8'hAA
	// slave transfer 8'h55
	// read one byte
	@(posedge clock)
	@(posedge clock)
	start = 1'b1;
	fifo_tx_readdata=8'hAA;
	fifo_tx_empty = 1'b0;
	spi_miso = 1'b0;
	
	@(negedge spi_clk)	
	fifo_tx_empty = 1'b1;
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(posedge done)
	start = 1'b0;

	// master transfer 8'hF0
	// slave transfer 8'h0F
	// read one byte
	@(posedge clock)
	start = 1'b1;
	fifo_tx_readdata=8'hF0;
	fifo_tx_empty = 1'b0;
	spi_miso = 1'b0;
	
	@(negedge spi_clk)	
	fifo_tx_empty = 1'b1;
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(posedge done)
	start = 1'b0;

	// write more than read
	// master transfer 8'hF0 8'hF0 8'hF0
	// slave transfer 8'h0F 8'bFF
	// read two byte
	@(posedge clock)
	start = 1'b1;
	fifo_tx_readdata=8'hF0;
	fifo_tx_empty = 1'b0;
	spi_miso = 1'b0;
	read_count = 8'd2;
	
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;

	@(posedge fifo_tx_re)
	@(posedge fifo_tx_re)
	@(posedge clock)
	fifo_tx_empty = 1'b1;
	@(posedge done)
	start = 1'b0;
	
	// read more than write
	// master transfer 8'hF0 
	// slave transfer 8'h0F 8'h0F
	// read two byte
	@(posedge clock)
	start = 1'b1;
	fifo_tx_readdata=8'hF0;
	fifo_tx_empty = 1'b0;
	spi_miso = 1'b0;
	read_count = 8'd2;
	
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b0;

	fifo_tx_empty = 1'b1;

	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b0;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b1;
	@(negedge spi_clk)	
	spi_miso = 1'b0;


	@(posedge done)
	start = 1'b0;
	

end

always
	#10 clock = ~clock;
endmodule
